#![windows_subsystem = "windows"]

use ascii_image::generate_ascii_image;
use fltk::{
    app::{self, App},
    dialog,
    enums::{CallbackTrigger, Font},
    prelude::*,
};
use fltk_theme::WidgetTheme;
use myuifile::UserInterface;
mod myuifile;

#[derive(Debug, Clone, Copy)]
enum Message {
    OpenImage,
    Generate,
    SaveAs,
}

struct MyApp {
    app: App,
    ui: UserInterface,
    receiver: app::Receiver<Message>,
    filename: Option<String>,
    ascii_image_string: Option<String>,
}
static SIMPLE_ASCII_CHARS: &str = "!\"#$%&'()*+,-./:;<=>?@[\\]^_`{|}~";

impl MyApp {
    fn new() -> Self {
        let app = App::default();
        let widget_theme = WidgetTheme::new(fltk_theme::ThemeType::Metro);
        widget_theme.apply();
        let (sender, receiver) = app::channel::<Message>();
        let mut ui = myuifile::UserInterface::make_window();
        ui.wind_main.set_label("Ascii Image");
        ui.button_open.emit(sender.clone(), Message::OpenImage);
        ui.button_save_as.emit(sender.clone(), Message::SaveAs);
        ui.input_custom_ascii.set_value(SIMPLE_ASCII_CHARS);
        ui.input_custom_ascii.set_trigger(CallbackTrigger::Changed);
        ui.input_custom_ascii
            .emit(sender.clone(), Message::Generate);
        ui.input_size.set_trigger(CallbackTrigger::Changed);
        ui.input_size.emit(sender.clone(), Message::Generate);
        ui.input_size.set_value("50");
        ui.input_image.set_text_font(Font::ScreenBold);

        Self {
            app,
            ui,
            receiver,
            filename: None,
            ascii_image_string: None,
        }
    }

    fn launch(&mut self) {
        while self.app.wait() {
            use Message::*;
            if let Some(msg) = self.receiver.recv() {
                match msg {
                    OpenImage => {
                        if let Some(filename) =
                            dialog::file_chooser("打开一张图片", "*.*", ".", true)
                        {
                            self.filename = Some(filename.clone());
                            let ascii_image = generate_ascii_image(
                                &filename,
                                self.ui.input_custom_ascii.value(),
                                self.ui.input_size.value().parse().unwrap(),
                            );
                            match ascii_image {
                                Ok(ascii_image) => {
                                    self.ascii_image_string = Some(ascii_image.clone());
                                    self.ui.input_image.set_value(&ascii_image);
                                }
                                Err(err) => {
                                    self.ascii_image_string = None;
                                    self.ui.input_image.set_value(&err.to_string());
                                }
                            }
                        }
                    }
                    Generate => {
                        if let Some(filename) = &self.filename {
                            let input_custom_ascii = self.ui.input_custom_ascii.value();
                            let input_custom_size = self.ui.input_size.value();
                            let custom_ascii_string = if input_custom_ascii.trim() == "" {
                                SIMPLE_ASCII_CHARS.to_string()
                            } else {
                                input_custom_ascii
                            };
                            let custom_size =
                                if input_custom_size.trim().parse::<u32>().unwrap() <= 0 {
                                    50
                                } else {
                                    input_custom_size.parse::<u32>().unwrap()
                                };
                            let ascii_image =
                                generate_ascii_image(filename, custom_ascii_string, custom_size);

                            match ascii_image {
                                Ok(ascii_image) => {
                                    self.ascii_image_string = Some(ascii_image.clone());
                                    self.ui.input_image.set_value(&ascii_image);
                                }
                                Err(err) => {
                                    self.ascii_image_string = None;
                                    self.ui.input_image.set_value(&err.to_string());
                                }
                            }
                        }
                    }
                    SaveAs => {
                        if let Some(ascii_string) = &self.ascii_image_string {
                            if let Some(filename) =
                                dialog::file_chooser("保存文字图片", "*.txt", ".", true)
                            {
                                match std::fs::write(filename, ascii_string) {
                                    Ok(_) => {
                                        dialog::alert(
                                            fltk::app::screen_size().0 as i32 / 2,
                                            fltk::app::screen_size().1 as i32 / 2,
                                            "保存成功",
                                        );
                                    }
                                    Err(err) => {
                                        self.ui.input_image.set_value(&err.to_string());
                                    }
                                }
                            }
                        }
                    }
                }
            }
            match app::event() {
                fltk::enums::Event::MouseWheel => match app::event_dy() {
                    app::MouseWheel::Up => {}
                    app::MouseWheel::Down => {}
                    _ => {}
                },
                _ => {}
            }
        }
    }
}

fn main() {
    let mut fltk_template = MyApp::new();
    fltk_template.launch();
}
